package com.physics.mps.module.comsol.builder.result;

import com.physics.mps.module.comsol.builder.Builder;
import com.physics.mps.module.comsol.enums.SolveEnum;
import com.physics.mps.module.comsol.vo.ResultVo;
import com.physics.mps.module.comsol.vo.Volume;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author mcsoft
 * @date 2023/10/16 14:41
 * @description comsol java 导出结果脚本构建
 */
public class ResultBuilder {

    private final Builder builder;

    public ResultBuilder(Builder builder) {
        this.builder = builder;
    }

    /**
     * buildVtu
     * @param resultFile
     */
    public void buildVtu(String resultFile) {

        String dataTag = builder.uniqueTag("data");
        String exportFeatureTag = builder.uniqueTag("exportFeature");

        builder.change(1, 2);
        builder.append("ExportFeature ");
        builder.append(exportFeatureTag);
        builder.append(" = model.result().export().create(");
        builder.value(dataTag);
        builder.append(", \"Data\");");

        builder.change(1, 2);
        builder.append(exportFeatureTag);
        builder.append(".set(\"exporttype\", \"vtu\");");

        builder.change(1, 2);
        builder.append(exportFeatureTag);
        builder.append(".set(\"filename\", ");
        builder.value(resultFile);
        builder.append(");");

        builder.change(1, 2);
        builder.append(exportFeatureTag);
        builder.append(".run();");
    }

    /**
     * 3D绘图
     * buildPlotGroup3D
     *  expr: rvib1.q2sq(solid.mises_rv)
     *
     * @param resultVo
     * @return
     */
    public String buildPlotGroup3D(ResultVo resultVo) {
        String pgTag = builder.uniqueTag("pg");
        String volTag = builder.uniqueTag("vol");
        String resultFeatureTag = builder.uniqueTag("resultFeature");

        String resultPlotGroup =
                "        ResultFeature resultFeature = model.result().create(\"%s\", \"PlotGroup3D\");\n" +
                "        resultFeature.create(\"%s\", \"Volume\");\n" +
                "        resultFeature.set(\"data\", \"%s\");\n" +
                "        resultFeature.set(\"showlegendsmaxmin\", true);\n" +
                "        resultFeature.set(\"showlegendsunit\", true);\n" +
                "        resultFeature.feature(\"%s\").set(\"expr\", \"%s\");\n" +
                "        resultFeature.run();";
        resultPlotGroup = String.format(resultPlotGroup, pgTag, volTag, resultVo.getDatasetTag(), volTag, resultVo.getExpression());

        resultPlotGroup = resultPlotGroup.replace("resultFeature", resultFeatureTag);

        builder.change(2, 0);
        builder.append(resultPlotGroup);
        return pgTag;
    }


    /**
     * 导出图片
     * @param pgTag
     * @param imgFile
     */
    public void buildImg(String pgTag, String imgFile) {
        String imgTag = builder.uniqueTag("img");
        String exportFeatureTag = builder.uniqueTag("exportFeature");

        String exportImg =
                "        ExportFeature exportFeatureTag = model.result().export().create(\"%s\", \"Image\");\n" +
                "        exportFeatureTag.set(\"size\", \"current\");\n" +
                "        exportFeatureTag.set(\"unit\", \"px\");\n" +
                "        exportFeatureTag.set(\"height\", \"600\");\n" +
                "        exportFeatureTag.set(\"width\", \"800\");\n" +
                "        exportFeatureTag.set(\"lockratio\", \"off\");\n" +
                "        exportFeatureTag.set(\"resolution\", \"96\");\n" +
                "        exportFeatureTag.set(\"antialias\", \"on\");\n" +
                "        exportFeatureTag.set(\"zoomextents\", \"on\");\n" +
                "        exportFeatureTag.set(\"fontsize\", \"9\");\n" +
                "        exportFeatureTag.set(\"colortheme\", \"globaltheme\");\n" +
                "        exportFeatureTag.set(\"customcolor\", new double[]{1, 1, 1});\n" +
                "        exportFeatureTag.set(\"background\", \"color\");\n" +
                "        exportFeatureTag.set(\"gltfincludelines\", \"on\");\n" +
                "        exportFeatureTag.set(\"title1d\", \"on\");\n" +
                "        exportFeatureTag.set(\"legend1d\", \"on\");\n" +
                "        exportFeatureTag.set(\"logo1d\", \"on\");\n" +
                "        exportFeatureTag.set(\"options1d\", \"on\");\n" +
                "        exportFeatureTag.set(\"title2d\", \"on\");\n" +
                "        exportFeatureTag.set(\"legend2d\", \"on\");\n" +
                "        exportFeatureTag.set(\"logo2d\", \"on\");\n" +
                "        exportFeatureTag.set(\"options2d\", \"off\");\n" +
                "        exportFeatureTag.set(\"title3d\", \"on\");\n" +
                "        exportFeatureTag.set(\"legend3d\", \"on\");\n" +
                "        exportFeatureTag.set(\"logo3d\", \"on\");\n" +
                "        exportFeatureTag.set(\"options3d\", \"on\");\n" +
                "        exportFeatureTag.set(\"axisorientation\", \"on\");\n" +
                "        exportFeatureTag.set(\"grid\", \"on\");\n" +
                "        exportFeatureTag.set(\"axes1d\", \"on\");\n" +
                "        exportFeatureTag.set(\"axes2d\", \"on\");\n" +
                "        exportFeatureTag.set(\"showgrid\", \"on\");\n" +
                "        exportFeatureTag.set(\"target\", \"file\");\n" +
                "        exportFeatureTag.set(\"qualitylevel\", \"92\");\n" +
                "        exportFeatureTag.set(\"qualityactive\", \"off\");\n" +
                "        exportFeatureTag.set(\"imagetype\", \"png\");\n" +
                "        exportFeatureTag.set(\"lockview\", \"off\");\n" +
                "        exportFeatureTag.set(\"sourceobject\", \"%s\");\n" +
                "        exportFeatureTag.set(\"pngfilename\", \"%s\");\n" +
                "        exportFeatureTag.run();";

        // imgTag pgTag imgTag
        exportImg = String.format(exportImg, imgTag, pgTag, imgFile);
        // exportFeatureTag -> exportFeatureTag
        exportImg = exportImg.replace("exportFeatureTag", exportFeatureTag);

        builder.change(2, 0);
        builder.append(exportImg);

    }


    /**
     *
     * 体最大值
     * 体最小值
     *
     * @param volumeResultPath
     * @param volumes
     */
    public void buildVolume(String geomTag, SolveEnum solve, String volumeResultPath, ResultVo resultVo) {
        List<Volume> volumes = resultVo.getVolumes();
        String volumeExpression = resultVo.getVolumeExpression();
        builder.change(1, 2);
        if (CollectionUtils.isEmpty(volumes)) {
            return;
        }

        // List 存储最大值最小值
        builder.append("java.util.List<String> results = new java.util.ArrayList<String>();", true);

        // type:name:maxValue:minValue
        builder.append("String lineFormat = \"%s:%s:%s:%s\";", true);

        for (Volume volume : volumes) {

            // 表格
            String maxTblTag = builder.uniqueTag("tbl");
            builder.append(String.format("model.result().table().create(\"%s\", \"Table\");", maxTblTag), true);
            String minTblTag = builder.uniqueTag("tbl");
            builder.append(String.format("model.result().table().create(\"%s\", \"Table\");", minTblTag), true);

            // 创建选择
            builder.change(1, 2);
            String ballSelect = builder.createBallSelect(volume.getEntityDim(), volume.getCoordinate());


            /**
             *      model.result().numerical("max1").setIndex("expr", "T1", 0);
             *      model.result().numerical("max1").setIndex("unit", "K1", 0);
             *
             *      rvib1.q2sq(solid.edeve)
             *      .set("innerinput", "all");
             */

            // 体最大值
            builder.change(1, 0);
            String maxTag = builder.uniqueTag("max");
            String maxNumericalFeature = builder.uniqueTag("maxNumericalFeature");
            builder.append(String.format("NumericalFeature %s = model.result().numerical().create(\"%s\", \"MaxVolume\");", maxNumericalFeature, maxTag), true);
            if (SolveEnum.RandomVibration.equals(solve)) {
                // 随机振动
                builder.append(maxNumericalFeature + ".setIndex(\"innerinput\", \"all\");", true);
            } else {
                // 传热
                builder.append(maxNumericalFeature + ".setIndex(\"looplevelinput\", \"last\", 0);", true);
            }
            builder.append(String.format("%s.setIndex(\"expr\", \"%s\", 0);", maxNumericalFeature, volumeExpression), true);
            builder.append(String.format("%s.set(\"table\", \"%s\");", maxNumericalFeature, maxTblTag), true);
            builder.append(String.format("%s.set(\"data\", \"%s\");", maxNumericalFeature, resultVo.getDatasetTag()), true);
            builder.append(String.format("%s.selection().named(\"%s_%s\");", maxNumericalFeature, geomTag, ballSelect), true);
            builder.append(maxNumericalFeature + ".setResult();", true);

            // 体最小值
            builder.change(1, 0);
            String minTag = builder.uniqueTag("min");
            String minNumericalFeature = builder.uniqueTag("minNumericalFeature");
            builder.append(String.format("NumericalFeature %s = model.result().numerical().create(\"%s\", \"MinVolume\");", minNumericalFeature, minTag), true);
            if (SolveEnum.RandomVibration.equals(solve)) {
                // 随机振动
                builder.append(minNumericalFeature + ".setIndex(\"innerinput\", \"all\");", true);
            } else {
                // 传热
                builder.append(minNumericalFeature + ".setIndex(\"looplevelinput\", \"last\", 0);", true);
            }
            builder.append(String.format("%s.setIndex(\"expr\", \"%s\", 0);", minNumericalFeature, volumeExpression), true);
            builder.append(String.format("%s.set(\"table\", \"%s\");", minNumericalFeature, minTblTag), true);
            builder.append(String.format("%s.set(\"data\", \"%s\");", minNumericalFeature, resultVo.getDatasetTag()), true);
            builder.append(String.format("%s.selection().named(\"%s_%s\");", minNumericalFeature, geomTag, ballSelect), true);
            builder.append(minNumericalFeature + ".setResult();", true);


            // 结果
            builder.change(1, 0);
            String maxResult = builder.uniqueTag("maxResult");
            String minResult = builder.uniqueTag("minResult");
            builder.append(String.format("double[][][] %s = %s.computeResult();", maxResult, maxNumericalFeature), true);
            builder.append(String.format("double[][][] %s = %s.computeResult();", minResult, minNumericalFeature), true);

            builder.change(1, 0);
            String maxValue = builder.uniqueTag("maxValue");
            String minValue = builder.uniqueTag("minValue");
            builder.append(String.format("double %s = %s[0][0][0];", maxValue, maxResult), true);
            builder.append(String.format("double %s = %s[0][0][0];", minValue, minResult), true);
            builder.append(String.format("results.add(String.format(lineFormat, \"%s\", \"%s\", %s, %s));", volume.getType(), volume.getName(), maxValue, minValue), true);


        }

        builder.change(2, 0);
        String writeResultFormat = "" +
                "        java.io.FileWriter fileWriter = null;\n" +
                "        try {\n" +
                "            java.io.File file = new java.io.File(\"%s\");\n" +
                "            if(!file.getParentFile().exists()) {\n" +
                "               file.getParentFile().mkdirs();\n" +
                "            }\n" +
                "            fileWriter = new java.io.FileWriter(file, true);\n" +
                "            for (String content: results) {\n" +
                "                fileWriter.append(content + \"\\n\");\n" +
                "            }\n" +
                "        } catch (java.io.IOException e) {\n" +
                "            e.printStackTrace(System.out);\n" +
                "            throw new RuntimeException(e);\n" +
                "        } finally {\n" +
                "            if (fileWriter != null) {\n" +
                "                try {\n" +
                "                    fileWriter.close();\n" +
                "                } catch (java.io.IOException e) {\n" +
                "                    throw new RuntimeException(e);\n" +
                "                }\n" +
                "            }\n" +
                "        }" +
                "";
        builder.append(String.format(writeResultFormat, volumeResultPath));
    }


}
